package io.sage.ch06.methodrefactoring;

/**
 * 6.8 Replace Method with Method Object 以函数对象取代函数
 * 问题场景：有一个大型函数，其中对局部变量的使用使你无法采用Extract Method
 * 重构思路：将这个函数放进一个单独对象中，如此一来局部变量就变成了对象内的字段，
 * 然后就可以在同一个对象中将这个大型函数分解为多个小型函数。
 * 做法：
 * 1）建立一个新类，根据待处理函数的用途，为这个类命名。
 * 2）在新类中创立一个final字段，用于保存原先大型函数所在的对象，即源对象。
 * 同时，针对原函数的每个临时变量和每个参数，在新类中建立一个对应的字段保存。
 * 3）在新类中建立一个构造函数，接受源对象即原函数的所有参数作为参数。
 * 4）在新类中建立一个compute()函数。
 * 5）将原函数的代码复制到compute()函数中，如果需要调用源对象的任何函数，请通过源对象字段调用。
 * 6）编译
 * 7）将旧函数的函数体替换为：创建新类的新对象，而后调用其compute()函数。
 */
public class ReplaceMethodwithMethodObject {


    /**
     * 重构前
     */
    class Account {
        private int delta() {
            return 0;
        }

        int gamma(int inputVal, int quantity, int yearToDate) {
            int importantValue1 = (inputVal * quantity) + delta();
            int importantValue2 = (inputVal * yearToDate) + 100;
            if ((yearToDate - importantValue1) > 100) {
                importantValue2 -= 20;
            }
            int importantValue3 = importantValue2 * 7;
            return importantValue3 - 2 * importantValue1;
        }
    }


    /**
     * 重构后
     */
    class Account_new {
        private int delta() {
            return 0;
        }

        int gamma(int inputVal, int quantity, int yearToDate) {
            return new Gamma(this, inputVal, quantity, yearToDate).compute();
        }
    }

    class Gamma {
        private final Account_new _account;
        private int inputVal;
        private int quantity;
        private int yearToDate;
        private int importantValue1;
        private int importantValue2;
        private int importantValue3;

        public Gamma(Account_new _account, int inputVal, int quantity, int yearToDate) {
            this._account = _account;
            this.inputVal = inputVal;
            this.quantity = quantity;
            this.yearToDate = yearToDate;
        }

        int compute() {
            int importantValue1 = (inputVal * quantity) + _account.delta();
            int importantValue2 = (inputVal * yearToDate) + 100;
//            if ((yearToDate - importantValue1) > 100) {
//                importantValue2 -= 20;
//            }
            importantThing();
            int importantValue3 = importantValue2 * 7;
            return importantValue3 - 2 * importantValue1;
        }

        /**
         * 源函数的变量已经变为新类的字段，所以可以直接使用Extract Method，不必担心参数传递问题。
         */
        void importantThing() {
            if ((yearToDate - importantValue1) > 100) {
                importantValue2 -= 20;
            }
        }
    }


}
